home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
client
/
client.c
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
13KB
|
516 lines
/*
* static char *rcsid_client_c =
* "$Id: client.c,v 1.18 1996/07/24 06:58:52 master Exp master $";
*/
/*
CrossFire, A Multiplayer game for X-windows
Copyright (C) 1992 Frank Tore Johansen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author can be reached via e-mail to frankj@ifi.uio.no.
*/
/* include "includes.h" so all the various system identifiers
* (ie, __sgi__, __sun__, etc) are set up correctly. A lot of
* the include files could probably be deleted below.
*/
#include <includes.h>
#include <config.h>
#ifdef SERVER
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <pwd.h>
#ifdef NCR
#include <sys/utsname.h>
#endif
#if defined(__sgi__) || defined(SVR4)
#ifndef SYS_NMLN
#define SYS_NMLN 257
#endif
#include <sys/systeminfo.h>
#endif
#if !defined (__STRICT_ANSI__) || defined (__sun__)
# if !defined (Mips) && !defined (vax) && !defined(ibm032)
# include <stdlib.h>
# endif
# if !defined (MACH) && !defined (sony) && !defined (vax) && !defined(ibm032) \
&& !defined (NeXT) && !defined(linux) && !defined(DMALLOC)
# include <malloc.h>
# endif
#endif
#ifndef NAME_MAX
# ifdef _POSIX_NAME_MAX
# define NAME_MAX pathconf("/dev/null", _POSIX_NAME_MAX)
# else
# ifdef MAXHOSTNAMELEN
# define NAME_MAX MAXHOSTNAMELEN
# else
# define NAME_MAX 256
# endif
# endif
#endif
#include <global.h> /* Sad to include the whole thing, only need libproto.h */
#include <version.h>
#ifndef __CEXTRACT__
#include "proto.h" /* My own prototyes, made by "make proto" */
#endif
int
main(int argc, char **argv, char **env)
{
char *dispname = (char *) getenv("DISPLAY");
char localdispname[65+6];
char *hostname = (char *) getenv("HOST");
char *optcmd = (char *) NULL;
char *ch, *p, *q;
char *username;
struct passwd *pwent;
struct protoent *protox;
Display *display;
struct sockaddr_in insock;
int i;
char buf[MAX_BUF], buf2[MAX_BUF];
int fd, fd2;
FILE *fpin,*fpout;
int set_pixmaps = 0, set_xpm = 0;
int set_split = 0;
int synchronize = (-1);
/*init_library();*/
init_globals();
init_function_pointers();
init_defaults();
for (i = 1; i < argc; i++)
{
int l = strlen(argv[i]);
if(l > 1)
{
if (!strncmp(argv[i], "-server", l))
{
if (++i == argc)
{
fprintf(stderr, "You must specify a hostname after -server.\n");
return 1;
}
hostname = argv[i];
continue;
}
if (!strncmp(argv[i], "-display", l))
{
if (++i == argc)
{
fprintf(stderr, "You must specify the display after -display.\n");
return 1;
}
dispname = argv[i];
continue;
}
if (!strncmp(argv[i], "-debug", l))
{
debug = 1;
continue;
}
if (!strncmp(argv[i], "-cmd", l))
{
if (++i == argc)
{
fprintf(stderr, "You must specify the command to run after -cmd.\n");
return 1;
}
optcmd = argv[i];
continue;
}
if (!strncmp(argv[i], "-pix", l))
{
set_pixmaps = 1;
continue;
}
if (!strncmp(argv[i], "-xpm", l))
{
set_xpm = 1;
continue;
}
if (!strncmp(argv[i], "-split", l) || !strcmp("w", argv[i]))
{
set_split = 1;
continue;
}
if (!strncmp(argv[i], "-synchronize", l))
{
if (++i == argc || !sscanf(argv[i], "%d", &synchronize))
{
fprintf(stderr, "You must specify a number after -synchronize.\n");
return 1;
}
continue;
}
if (!strncmp(argv[i], "-help", l))
usage(argv[0]);
}
fprintf(stderr,"Unknown argument: %s.\n",argv[i]);
usage(argv[0]);
}
if (hostname == (char *) NULL)
{
fprintf(stderr, "You must set the HOST environment variable.\n");
fprintf(stderr, "(Or specify server with the -server option.)\n");
return 1;
}
if ((pwent = getpwuid(getuid())) == (struct passwd *) NULL)
{
fprintf(stderr, "Can't find your username.\n");
return 1;
}
username = strdup_local(pwent->pw_name);
if (optcmd == (char *) NULL)
{
if (dispname == (char *) NULL)
{
fprintf(stderr, "You must set the DISPLAY environment variable.\n");
fprintf(stderr, "(Or specify it with the -display option.)\n");
return 1;
}
if (*dispname == ':')
{
char localhostname[65+6];
#ifdef SVR4
if (sysinfo(SI_HOSTNAME, localhostname, NAME_MAX) <0) {
fprintf(stderr, "Can't get local hostname.\n");
perror("%s: SI_HOSTNAME");
}
#else /* Assume BSD */
if (gethostname(localhostname, 65))
{
fprintf(stderr, "Can't get local hostname.\n");
perror("gethostname ");
}
#endif
sprintf(localdispname, "%s%s", localhostname, dispname);
dispname = localdispname;
}
if ((display = XOpenDisplay(dispname)) == (Display *) NULL)
{
fprintf(stderr, "Can't open display %s.\n",dispname);
return 1;
}
if (!set_pixmaps && !set_xpm && !check_font_path(display))
{
fprintf(stderr,"Trying to fix fontpath for %s.\n",dispname);
fflush(stderr);
set_font_path(display,FONTDIR);
if (!check_font_path(display))
{
fprintf(stderr,"Failed to fix the fontpath.\n");
return 1;
}
}
XCloseDisplay(display);
}
/* End of X-stuff, over to socket-stuff... */
protox = getprotobyname("tcp");
if (protox == (struct protoent *) NULL)
{
fprintf(stderr, "Error getting prorobyname (tcp)\n");
return 1;
}
fd = socket(PF_INET, SOCK_STREAM, protox->p_proto);
if (fd == (-1))
{
perror("Error on socket command");
return 1;
}
insock.sin_family = AF_INET;
insock.sin_port = htons((unsigned short)PORT);
if (isdigit(*hostname))
{
insock.sin_addr.s_addr = inet_addr(hostname);
sprintf(buf,"xhost +%s",hostname);
}
else
{
struct hostent *hostbn = gethostbyname(hostname);
if (hostbn == (struct hostent *) NULL)
{
fprintf(stderr,"Unknown host: %s\n",hostname);
return 1;
}
#if defined(__sun__) || defined(SVR4)
memcpy(&insock.sin_addr, hostbn->h_addr, hostbn->h_length);
#else
bcopy(hostbn->h_addr, &insock.sin_addr, hostbn->h_length);
#endif
sprintf(buf,"xhost +%s",hostbn->h_name);
}
#ifndef SECURE /* I don't like xhost + */
if (optcmd == (char *) NULL)
{
fprintf(stderr,"%s\n",buf);
system(buf);
}
#endif
if (connect(fd,(struct sockaddr *)&insock,sizeof(insock)) == (-1))
{
perror("Can't connect to server");
return 1;
}
fd2 = dup(fd);
fpin = fdopen(fd,"r");
fpout = fdopen(fd2,"w");
fputs("version\n",fpout);
fflush(fpout);
fgets(buf, MAX_BUF-1, fpin);
if (!strncmp(buf, "Welcome",7)) {
if (fgets(buf, MAX_BUF-1, fpin)==NULL) {
fprintf(stderr,"Syntax error in remote version: %s",buf);
return 1;
}
}
if ((ch = strchr(buf, 'v')) == NULL) {
fprintf(stderr,"Syntax error in remote version: %s",buf);
return 1;
}
else
if(compare_versions(++ch))
return 1;
fprintf(fpout,"listen 0\n");
fflush(fpout);
if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr, "Failed to set listen to 0: %s", buf);
return 1;
}
fprintf(fpout,"name %s\n",username);
fflush(fpout);
if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr, "Failed to set name: %s", buf);
return 1;
}
if (set_xpm)
{
fputs("set xpm\n", fpout);
fflush(fpout);
if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr, "Failed to set XPM mode (server might not have it enabled): %s", buf);
return 1;
}
}
else if (set_pixmaps)
{
fputs("set pixmaps\n", fpout);
fflush(fpout);
if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr, "Failed to set pixmaps: %s", buf);
return 1;
}
}
else {
fputs("set font\n", fpout);
fflush(fpout);
if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr, "Failed to select font mode: %s", buf);
return 1;
}
}
if (set_split)
{
fputs("set split\n", fpout);
fflush(fpout);
if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr, "Failed to set split windows: %s", buf);
return 1;
}
}
if (synchronize != (-1))
{
fprintf(fpout, "synchronize %d\n", synchronize);
fflush(fpout);
if (fgets(buf, MAX_BUF-1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr, "Failed to set synchronize: %s", buf);
return 1;
}
}
if (optcmd != NULL) {
set_protocol(fpin, fpout, 1);
strcpy (q = buf2, optcmd);
do {
if ((p = strchr (q, ';')))
*p = '\0';
fprintf(fpout,"%s\n", q);
q = p + 1;
fflush(fpout);
while(fgets(buf, MAX_BUF - 1, fpin) != NULL && strcmp(buf,"EOT\n"))
fprintf(stderr,"%s",buf);
} while (p);
}
else /* Default command is add... */
{
fprintf(fpout,"add %s\n",dispname);
fflush(fpout);
if (fgets(buf, MAX_BUF - 1, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr,"Failed to add %s: %s",dispname,buf);
return 1;
}
}
fputs("quit\n",fpout);
fflush(fpout);
if (fgets(buf, MAX_BUF - 1, fpin) != NULL)
{
fclose(fpin);
fclose(fpout);
}
close(fd2); /* Hmm, why do I bother... */
close(fd);
return 0;
}
void
set_protocol(FILE *fpin, FILE *fpout, int p)
{
char buf[256];
fprintf(fpout,"protocol %d\n",p);
fflush(fpout);
if (fgets(buf, 250, fpin) == NULL || strcmp(buf,"OK.\n"))
{
fprintf(stderr,"Failed to set protocol.\n");
exit(1);
}
if (p == 1)
if(fgets(buf, 250,fpin) == NULL || strcmp(buf,"EOT\n"))
{
fprintf(stderr, "Protocol 1 out of order.\n");
exit(1);
}
}
int
compare_versions(char *remote_ver)
{
#if 1
return 0;
#else
int remote_version,remote_subversion,remote_patchlevel;
int client_version,client_subversion,client_patchlevel;
int remote_sum, client_sum;
if(sscanf(remote_ver,"%d.%d.%d",
&remote_version,&remote_subversion,&remote_patchlevel) != 3)
{
fprintf(stderr, "Failed to decode remote version: %s\n",remote_ver);
return 1;
}
sscanf(VERSION,"%d.%d",&client_version,&client_subversion);
sscanf(PATCH,".%d",&client_patchlevel);
remote_sum = remote_version*10000 + remote_subversion*100 + remote_patchlevel;
client_sum = client_version*10000 + client_subversion*100 + client_patchlevel;
if (remote_sum > client_sum)
{
fprintf(stderr,"You will need to get a newer version of crossclient,\n");
fprintf(stderr,"at least version %s (this is %s%s)\n",
remote_ver,VERSION,PATCH);
return 1;
}
if (remote_sum < client_sum)
{
fprintf(stderr,
"Warning: The remote version is older than your client version.\n");
fprintf(stderr,"(It should still be backward compatible with your font)\n");
}
return 0;
#endif
}
void
usage(char *progname)
{
char *ch = strrchr(progname, '/');
fprintf(stderr, "Usage: %s [options]\n",
(ch == (char *) NULL ? progname : ch + 1));
fprintf(stderr,"Options:\n");
fprintf(stderr,
"-server <name> - Connect to <name> instead of \"localhost\".\n");
fprintf(stderr,
"-display <name> - Use <name> instead of the DISPLAY environment var.\n");
fprintf(stderr,
"-pix - Use pixmaps instead of fonts.\n");
fprintf(stderr,
"-xpm - Use color pixmaps (XPM) instead of fonts.\n");
fprintf(stderr,
" Note: Some servers may not support this\n");
fprintf(stderr,
"-split - Use split windows.\n");
fprintf(stderr,
"-cmd <command> - Specify an other command than the default \"add\".\n");
fprintf(stderr,
" Try \"help\" as <command> to see what is allowed.\n");
fprintf(stderr,
"-debug - Turn on debugging.\n");
fprintf(stderr,
"-synchronize <nr>- Specifies frequency of synchronize Vs flush.\n");
fprintf(stderr,
"-help - Display this information.\n");
exit(0);
}
#else
#include <stdio.h>
#ifdef __sun__
int fprintf();
#endif
int
main(int argc, char **argv, char **env)
{
(void) fprintf(stderr,
"You have to define \"SERVER\" in include/config.h if you\n");
(void) fprintf(stderr,"want the client to work.\n");
return 0;
}
#endif